package com.engr.springbooteasypoi.thread;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程-消费者模式
 */
public class ThreadComsumerDesign {

    public static void main(String[] args) {
        Godown godown = new Godown(20);
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, 10, 10L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>());
        Consumer consumer1 = new Consumer(10, godown);
        Consumer consumer2 = new Consumer(15, godown);
        Consumer consumer3 = new Consumer(10, godown);

        Producer producer = new Producer(5, godown);
        Producer producer2 = new Producer(15, godown);
        Producer producer3 = new Producer(15, godown);
        Producer producer4 = new Producer(15, godown);
        poolExecutor.execute(producer);
        poolExecutor.execute(consumer2);
        poolExecutor.execute(consumer1);
        poolExecutor.execute(consumer3);


        poolExecutor.shutdown();
        System.out.println("当前仓库剩余储仓量->" + godown.curnum);

        /*Godown godown = new Godown(30);
        Consumer c1 = new Consumer(50, godown);
        Consumer c2 = new Consumer(35, godown);
        Consumer c3 = new Consumer(30, godown);
        Producer p1 = new Producer(10, godown);
        Producer p2 = new Producer(10, godown);
        Producer p3 = new Producer(10, godown);
        Producer p4 = new Producer(10, godown);
        Producer p5 = new Producer(10, godown);
        Producer p6 = new Producer(10, godown);
        Producer p7 = new Producer(80, godown);

        c1.start();
        c2.start();
        c3.start();
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();
        p6.start();
        p7.start();*/
    }
}

class Godown {

    // 最大库存量
    public static final int MAX_SIZE = 100;

    // 当前库存量
    public int curnum;

    Godown() {

    }

    public Godown(int curnum) {
        this.curnum = curnum;
    }

    /**
     * 生产指定数量产品
     */
    public synchronized void produce(int neednum) {
        // 测试是否需要生产
        while (neednum + curnum > MAX_SIZE) {
            System.out.println("要生产的产品数量:" + neednum + " 超过剩余库存量" + (MAX_SIZE - curnum) + ",暂时不能生产任务！");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 满足生产条件,则进行生产,这里简单的更改当前库存量
        curnum += neednum;
        System.out.println("已经生产了 " + neednum + "个产品,现仓储量为:" + curnum);
        notifyAll();
    }

    /**
     * 消费指定数量的产品
     */
    public synchronized void consume(int neednum) {
        // 判断是否可消费
        while (neednum > curnum) {
            try {
                wait(); // 使当前线程处于等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 满足消费条件
        curnum -= neednum;
        System.out.println("已经消费了:" + neednum + ",当前仓储量为:" + curnum);
        notifyAll(); // 唤醒当前所有等待的线程

    }

}

class Producer extends Thread {

    private int neednum;                //生产产品的数量
    private Godown godown;            //仓库

    Producer(int neednum, Godown godown) {
        this.neednum = neednum;
        this.godown = godown;
    }

    @Override
    public void run() {
        //生产指定数量的产品
        godown.produce(neednum);
    }
}

/**
 * 消费者
 */
class Consumer extends Thread {

    private int neednum;

    private Godown godown;

    public Consumer(int neednum, Godown godown) {

        this.neednum = neednum;
        this.godown = godown;
    }

    @Override
    public void run() {
        // 消费指定产品数量
        godown.consume(neednum);
    }
}